package com.nodecollege.cloud.service.impl;

import com.nodecollege.cloud.common.UpmsConstants;
import com.nodecollege.cloud.common.constants.NCConstants;
import com.nodecollege.cloud.common.exception.UpmsException;
import com.nodecollege.cloud.common.model.IdName;
import com.nodecollege.cloud.common.model.LoginAdmin;
import com.nodecollege.cloud.common.model.QueryVO;
import com.nodecollege.cloud.common.model.po.*;
import com.nodecollege.cloud.common.model.vo.LoginVO;
import com.nodecollege.cloud.common.model.vo.MenuTreeVO;
import com.nodecollege.cloud.common.utils.NCUtils;
import com.nodecollege.cloud.common.utils.RedisUtils;
import com.nodecollege.cloud.core.utils.PasswordUtil;
import com.nodecollege.cloud.dao.mapper.UpmsAdminPasswordMapper;
import com.nodecollege.cloud.dao.mapper.UpmsMenuMapper;
import com.nodecollege.cloud.dao.mapper.UpmsOpRoleMapper;
import com.nodecollege.cloud.service.AdminLoginService;
import com.nodecollege.cloud.service.AdminService;
import com.nodecollege.cloud.service.PasswordPolicyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author LC
 * @date 2019/12/1 12:14
 */
@Service
public class AdminLoginServiceImpl implements AdminLoginService {

    private static Long expire = 2 * 60 * 60L;

    @Autowired
    private PasswordPolicyService passwordPolicyService;

    @Autowired
    private AdminService adminService;

    @Autowired
    private UpmsAdminPasswordMapper adminPasswordMapper;

    @Autowired
    private UpmsOpRoleMapper opRoleMapper;

    @Autowired
    private UpmsMenuMapper menuMapper;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 管理员登陆
     *
     * @param loginVO
     */
    @Override
    public LoginAdmin login(LoginVO loginVO) {
        // 1 登陆前验证密码策略
        passwordPolicyService.checkLoginPolicy(loginVO.getAccount(), loginVO.getPassword(),
                loginVO.getPassword(), loginVO.getImageCert());

        // 2 验证密码是否正确
        UpmsAdmin admin = adminService.getAdminByAccount(loginVO.getAccount());
        List<UpmsAdminPassword> passwordList = adminPasswordMapper.selectListByAdminId(admin.getAdminId());

        if (passwordList == null || passwordList.isEmpty() || !passwordList.get(0).getPassword()
                .equals(PasswordUtil.md5(loginVO.getPassword(), passwordList.get(0).getSalt()))) {
            Integer loginFileNum = passwordPolicyService.setLoginFileNum(loginVO.getAccount());
            throw new UpmsException("-1", MessageFormat.format("密码错误！请重新输入！(第{0}次)", loginFileNum));
        }

        // 3 登陆成功后校验密码策略
        passwordPolicyService.checkLoginSuccessPolicy(admin, passwordList,
                loginVO.getNewPassword(), loginVO.getImageCert());

        // 4 生成token
        String accessToken = NCUtils.getUUID();
        LoginAdmin loginAdmin = new LoginAdmin();
        loginAdmin.setUserId(admin.getAdminId());
        loginAdmin.setAccount(admin.getAccount());
        loginAdmin.setName(admin.getTelephone());
        loginAdmin.setAccessToken(accessToken);
        loginAdmin.setInfoRandom(NCUtils.getUUID());
        loginAdmin.setExpire(expire);
        loginAdmin.setRoleList(new ArrayList<>());

        // 查询拥有的角色
        QueryVO<UpmsOpRoleAdmin> queryRole = new QueryVO<>(new UpmsOpRoleAdmin());
        queryRole.getData().setAdminId(admin.getAdminId());
        List<UpmsOpRole> roleList = opRoleMapper.selectListByRoleAdmin(queryRole.toMap());
        Set<UpmsMenu> menuSet = new HashSet<>();
        roleList.forEach(item -> {
            loginAdmin.getRoleList().add(new IdName(item.getOpRoleId(), item.getRoleName()));
            QueryVO<UpmsOpRoleMenu> queryMenu = new QueryVO<>(new UpmsOpRoleMenu());
            queryMenu.getData().setOpRoleId(item.getOpRoleId());
            menuSet.addAll(menuMapper.selectListByOpRoleMenu(queryMenu.toMap()));
        });
        List<UpmsMenu> menuList = new ArrayList<>(menuSet);
        loginAdmin.setMenuTree(MenuTreeVO.getMenuTree(menuList));

        redisUtils.set(UpmsConstants.ADMIN_LOGIN_INFO + accessToken, loginAdmin, expire);

        // 清除登录失败次数缓存
        passwordPolicyService.deleteLoginFileNum(loginVO.getAccount());
        return loginAdmin;
    }

    /**
     * 用户注册
     *
     * @param loginVO
     */
    @Override
    public void register(LoginVO loginVO) {
        // 1 验证密码注册策略
        passwordPolicyService.checkRegisterPolicy(loginVO.getPassword(), loginVO.getAccount());

        // 2 注册管理员
        loginVO.setSource(NCConstants.INT_0);
        adminService.addAdmin(loginVO);
    }

    /**
     * 根据token获取登陆管理员信息
     *
     * @param token
     * @return
     */
    @Override
    public LoginAdmin getAdminInfo(String token) {
        return redisUtils.get(UpmsConstants.ADMIN_LOGIN_INFO + token, LoginAdmin.class);
    }

    /**
     * 退出登陆
     *
     * @param token
     */
    @Override
    public void logout(String token) {
        redisUtils.delete(UpmsConstants.ADMIN_LOGIN_INFO + token);
    }
}
